#include "ioctrl.h"
#include <QDebug>

IoCtrl::IoCtrl()
{
    m_pSerialPort = new QSerialPort;
    m_pTimer      = new QTimer;
    m_pSerialPort->setReadBufferSize(9);
    connect(m_pSerialPort, &QSerialPort::readyRead, this, &IoCtrl::serialDataArrived);
    connect(m_pTimer, SIGNAL(timeout()),this,SLOT(slotReadStatus()));
}
bool IoCtrl::open(QString strCom)
{
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        // 记录可供使用串口的Name、Description和Manufacturer，便于查找串口无法打开原因
        qDebug() << QObject::tr("available port: [%1:%2:%3]")
                       .arg(info.portName())
                       .arg(info.description())
                       .arg(info.manufacturer());
    }
    qDebug() << strCom;
    m_pSerialPort -> setPortName(strCom);
    bool bRlt = m_pSerialPort->open(QIODevice::ReadWrite);
    m_pSerialPort->setBaudRate(9600);
    m_pSerialPort->setDataBits(QSerialPort::Data8);
    m_pSerialPort->setParity(QSerialPort::NoParity);
    m_pSerialPort->setStopBits(QSerialPort::OneStop);
    m_pSerialPort->setFlowControl(QSerialPort::NoFlowControl);

    m_pSerialPort->setReadBufferSize(9);

    if(!bRlt)
    {
        emit sigMsg(QObject::tr("打开串口失败，错误原因[%1]")
                    .arg(m_pSerialPort->errorString()));
    }
    m_pTimer->start(500);
    return bRlt;
}

bool IoCtrl::close()
{
    m_pSerialPort->close();
}

bool IoCtrl::sendcommand(int nWay,bool bOpen,quint8 nData)
{
    bool bRlt = false;
    switch (nWay) {
    case WAY::Bit :
        bRlt = bitBarrier(bOpen,nData);
        break;
    case WAY::Group :
        bRlt = groupBarrier(bOpen,nData);
        break;
    case WAY::All :
        bRlt = allBarrier(bOpen);
        break;
    default:
        break;
    }
    return bRlt;
}

bool IoCtrl::bitBarrier(bool bOpen,quint8 nData)
{
    QByteArray ba;
    if(bOpen)
    {
       ba.append(char(COMMOND::BITOPEN));
    }
    else
    {
        ba.append(char(COMMOND::BITCLOSE));
    }
    ba.append(char(nData));
    wrapFrame(ba);
    qint64 nByteWritten;
    if(m_pSerialPort->isOpen()){
        nByteWritten=m_pSerialPort->write(ba);
        m_pSerialPort->flush();
    }
    else
    {
        emit sigMsg("串口未打开");
    }
    if (nByteWritten==ba.length())
    {
        emit sigMsg("位操作写入成功");
    }
    else
    {
        emit sigMsg("位操作写入失败");
    }
}

bool IoCtrl::groupBarrier(bool bOpen,quint8 nData)
{
    QByteArray ba;
    if(bOpen)
    {
       ba.append(char(COMMOND::GROUPOPEN));
    }
    else
    {
        ba.append(char(COMMOND::GROUPCLOSE));
    }
    ba.append(char(nData));
    wrapFrame(ba);
    qint64 nByteWritten;
    if(m_pSerialPort->isOpen()){
        nByteWritten=m_pSerialPort->write(ba);
        m_pSerialPort->flush();
    }
    else
    {
        emit sigMsg("串口未打开");
    }
    if (nByteWritten==ba.length())
    {
        emit sigMsg("组操作写入成功");
    }
    else
    {
        emit sigMsg("组操作写入失败");
    }
}

bool IoCtrl::allBarrier(bool bOpen)
{
    QByteArray ba;
    if(bOpen)
    {
       ba.append(char(COMMOND::ALLOPEN));
    }
    else
    {
        ba.append(char(COMMOND::ALLCLOSE));
    }
    quint8 nData = 0x00;
    ba.append(char(nData));
    wrapFrame(ba);
    qint64 nByteWritten;
    if(m_pSerialPort->isOpen()){
        nByteWritten=m_pSerialPort->write(ba);
        m_pSerialPort->flush();
    }
    else
    {
        emit sigMsg("串口未打开");
    }
    if (nByteWritten==ba.length())
    {
        emit sigMsg("全操作写入成功");
    }
    else
    {
        emit sigMsg("全操作写入失败");
    }
}

void IoCtrl::wrapFrame(QByteArray &data)
{
    data.prepend("\x00\x5A\x53\x00", 4);
    data.append("\x00\x00", 2);
    quint8 bcc = getCheckSum(data);
    data.append(bcc);
//    qDebug() << data.toHex();
}

quint8 IoCtrl::getCheckSum(QByteArray &data)
{
    quint8 n=0x00;
    for(int it=0; it<data.length(); ++it)
    {
        n += data[it];
    }
    return n;
}

void IoCtrl::serialDataArrived()
{
    data += m_pSerialPort->readAll();
    QByteArray da;
    da.append("\x00\x5a\x53\x00\x07",5);
    if(data.size() == 9)
    {
        if(data.startsWith(da))
        {
           processFrame(data);
        }
        data.clear();
    }
}

void IoCtrl::processFrame(QByteArray &data)
{
    if(data.size() != 9)
    {
        qDebug() << "串口采集到的数据有误";
        return;
    }
    uint da = uint(data.at(6));
    if(0 == (da & 0x01))
    {
        emit sigInput(0,true);
        qDebug() << "X0 有信号";
    }
    else
    {
        emit sigInput(0,false);
    }
    if(0 == (da & 0x02))
    {
        emit sigInput(1,true);
        qDebug() << "X1 有信号";
    }
    else
    {
        emit sigInput(1,false);
    }
    if(0 == (da & 0x04))
    {
        emit sigInput(2,true);
        qDebug() << "X2 有信号";
    }
    else
    {
        emit sigInput(2,false);
    }
    if(0 == (da & 0x08))
    {
        emit sigInput(3,true);
        qDebug() << "X3 有信号";
    }
    else
    {
        emit sigInput(3,false);
    }
}

void IoCtrl::slotReadStatus()
{
     QByteArray ba;
     ba.append(char(COMMOND::READSTATUS));
     ba.append("\x00",1);
     wrapFrame(ba);
     qint64 nByteWritten;
     if(m_pSerialPort->isOpen()){
         nByteWritten=m_pSerialPort->write(ba);
         m_pSerialPort->flush();
     }
     else
     {
         emit sigMsg("串口未打开");
     }

     if (nByteWritten==ba.length())
     {
         emit sigMsg("读状态写入成功");
     }
     else
     {
         emit sigMsg("读状态写入失败");
     }
}
